package com.youdianstar.app.common.base

import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.os.IBinder
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.youdianstar.app.common.base.BaseViewModel.Companion.BUNDLE
import com.youdianstar.app.common.base.BaseViewModel.Companion.CLASS
import com.youdianstar.app.common.callback.NetworkStateManager
import com.youdianstar.app.common.ex.getVmClazz
import com.youdianstar.app.common.util.AppManager
import com.youdianstar.app.common.util.dialog.DialogUtil

import com.youdianstar.app.common.auko.AnkoInternals



/**
 * File: BaseVmActivity
 * Author: 82149 Create: 2021/9/18 17:01
 * Changes (from 2021/9/18)
 * --------------------------------------------------
 * description:
 * --------------------------------------------------
 *
 */
 abstract class BaseBMActivity<DB : ViewDataBinding,VM : BaseViewModel>  : AppCompatActivity() {
    lateinit var mBinding: DB
    lateinit var mViewModel: VM
    private var viewModelId: Int? = null

    abstract fun layoutId(): Int

    abstract fun initVariableId(): Int?

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initContentCreate()
        initDataBind()
        viewModelId = initVariableId()
        mViewModel = initViewModel()!!
        //关联viewModel
        viewModelId?.let { mBinding.setVariable(it, mViewModel) }
        //让ViewModel拥有View的生命周期感应: 用了 kolin 就不要这一步
        mViewModel.let { lifecycle.addObserver(it) }

        AppManager.instance.addActivity(this)

        init(savedInstanceState)
    }

    private fun initDataBind() {
        mBinding = DataBindingUtil.setContentView(this, layoutId())
        mBinding.lifecycleOwner = this
    }

    /**创建ViewModel 方法0:配合koin使用,需要网络接口时*/
    abstract fun initViewModel(): VM?

    /**创建ViewModel*/
    fun createViewModel(): VM {
        return ViewModelProvider(this)[getVmClazz(this)]
    }

    private fun init(savedInstanceState: Bundle?) {
        registerUIChangeLiveDataCallBack()
        initView(savedInstanceState)
        initViewLayout()
        initData()
        initLiveObserver()
        initClickEvent()
        NetworkStateManager.instance.mNetworkStateCallback.observe(this, Observer {
            onNetworkStateChanged(it)
        })
    }

    override fun onDestroy() {
        super.onDestroy()
        mViewModel.let {
            lifecycle.removeObserver(it)
        }
        mBinding.unbind()
        AppManager.instance.removeActivity(this)
    }

    abstract fun initContentCreate()

    abstract fun initView(savedInstanceState: Bundle?)

    abstract fun initViewLayout()

    abstract fun initData()

    abstract fun initLiveObserver()

    abstract fun initClickEvent()

    /**
     * 网络变化监听 子类重写
     */
    open fun onNetworkStateChanged(isNetConnect: Boolean) {}

    private fun registerUIChangeLiveDataCallBack(){
        mViewModel.finishEvent.observe(this, Observer {
            finish()
        })
        mViewModel.backPressedEvent.observe(this, Observer {
            onBackPressed()
        })
        mViewModel.startActivityEvent.observe(this, Observer { t ->

            val activity: Class<out Activity> = t[CLASS] as Class<out Activity>
            val params: Array<out Pair<String, Any?>> = t[BUNDLE] as Array<out Pair<String, Any?>>
            startActivity(AnkoInternals.createIntent(this, activity, params))
        })

        mViewModel.loadingNetEvent.observe(this, Observer {
            showLoadingDialog(it)
        })
        mViewModel.dismissNetEvent.observe(this, Observer {
            dismissDialog()
        })
    }

    /**
     * dialog展示
     */
    fun showLoadingDialog(title: String?=null) {
        DialogUtil.instance.showLoading(this)
    }

    /**
     * 取消
     */
    fun dismissDialog() {
        DialogUtil.instance.dismissLoading()
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
        if (event.action == MotionEvent.ACTION_DOWN) {
            this.currentFocus?.let {  focus ->
                if (focus.windowToken != null) {
                    imm.hideSoftInputFromWindow(focus.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
                }
            }
        }
        return super.onTouchEvent(event)
    }

    /**
     * 判定当前是否需要隐藏
     */
    open fun isShouldHideKeyBord(v: View, ev: MotionEvent): Boolean {
        if (v is EditText) {
            val l = intArrayOf(0, 0)
            v.getLocationInWindow(l)
            val left = l[0]
            val top = l[1]
            val bottom = top + v.getHeight()
            val right = left + v.getWidth()
            return !(ev.x > left && ev.x < right && ev.y > top && ev.y < bottom)
        }
        return false
    }

    /**
     * 隐藏软键盘
     */
    open fun hideSoftInput(token: IBinder) {
        try {
            val manager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            manager.hideSoftInputFromWindow(
                token,
                InputMethodManager.HIDE_NOT_ALWAYS
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 隐藏键盘
     *
     * @param v edit
     */
    open fun hideInputKeyboard(v: EditText) {
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(v.windowToken, 0)
        v.clearFocus()
    }

    /**
     * 隐藏软键盘(只适用于Activity，不适用于Fragment)
     *
     * @param activity view
     */
    open fun hideSoftKeyboard(activity: Activity) {
        val view = activity.currentFocus
        view?.let {
            val inputMethodManager = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
            inputMethodManager.hideSoftInputFromWindow(
                it.windowToken,
                InputMethodManager.HIDE_NOT_ALWAYS
            )
        }
    }

    fun showKeyBoard(view: View) {
        val input = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        view.requestFocus()
        input.showSoftInput(view,0)
    }
}